/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * This file is part of retabel.
 *
 * Copyright (c) 2011 by individual contributors as indicated by the
 * @author tags. See the copyright.txt file in the distribution
 * for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.retabel.web.rest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.retabel.service.render.RenderService;

/**
 * Render REST interface implementation
 * <p/>
 * <h3>Extra-Info</h3>
 * Created: 10:19 16.07.11
 *
 * @author Burt Parkers, Peter Herber
 * @version 1.0
 */
@Path("/render")
@Stateless
public class RenderServiceBean extends RestServiceBean {

    private static final Logger logger = LoggerFactory.getLogger(RenderServiceBean.class);

    @EJB
    private RenderService renderService;

    @POST
    @Consumes("application/zip")
    @Produces(MediaType.TEXT_PLAIN)
    public Response render(@QueryParam("data") @DefaultValue("data.xml") String dataName,
                           @QueryParam("config") @DefaultValue("config.xml") String configName, byte[] renderData,
                           @Context UriInfo uriInfo) {
        PlainTextResponseBuilder response = new PlainTextResponseBuilder(uriInfo);

        response.println("Attempting to render design ...");

        try {
            Map<String, byte[]> contentMap = retrieveZipContent(renderData);

            byte[] configData = contentMap.get(configName);
            response.println("xmlData: [" + configData.length + "]");

            byte[] documentConfigData = contentMap.get(dataName);
            response.println("xmlData: [" + documentConfigData.length + "]");

            String uniqueRenderedDocumentIdentifier = renderService.render(configData, documentConfigData);

            // add the unique rendered document identifier as header parameter
            response.addCustomHeaderParameter("X-unique-rendered-document-identifier", uniqueRenderedDocumentIdentifier);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            response.println("Fatal error while uncompressing data file: " + e.getMessage());

            return response.getServerErrorResponse();
        }

        return response.getResponse();
    }

    private Map<String, byte[]> retrieveZipContent(byte[] content) throws IOException {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(content);
        ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(inputStream));
        ZipEntry entry;

        Map<String, byte[]> contentMap = new HashMap<>();

        while ((entry = zipInputStream.getNextEntry()) != null) {
            String entryName = entry.getName();
            if (!entry.isDirectory()) {
                byte[] partData = unzipEntry(zipInputStream);

                logger.debug("Size of entry: " + entryName + ", " + partData.length);

                contentMap.put(entryName, partData);
            }
        }
        return contentMap;
    }

    private byte[] unzipEntry(ZipInputStream zipInputStream) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (int c = zipInputStream.read(); c != -1; c = zipInputStream.read()) {
            baos.write(c);
        }
        return baos.toByteArray();
    }

}
